﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using RSSFeedReader.Data.Models;
using RSSFeedReader.Resources;

namespace RSSFeedReader.Data.Utilities
{
    /// <summary>
    /// Class to handle import/export of feeds.
    /// </summary>
    public static class ImportExport
    {
        #region Import
        /// <summary>
        /// Import feeds from XML data file.
        /// </summary>
        /// <param name="file">
        /// The XML file to import.
        /// </param>
        public static void Import(string file)
        {
            List<string> urls;
            XElement importXml = null;
            IEnumerable<XElement> feedsEnumerable = null;

            urls = new List<string>();

            try
            {
                importXml = XElement.Load(file);
                importXml = importXml.Element("body");

                if (importXml.HasElements)
                {
                    // Get all the outlines in body node
                    feedsEnumerable = importXml.Elements("outline").ToList();

                    foreach (XElement feed in feedsEnumerable)
                    {
                        if (!feed.HasElements)
                        {
                            // Then must be a RSS Feed
                            ChannelDataSource.Instance.AddChannel(feed.Attribute("xmlUrl").Value);
                        }
                        else
                        {
                            // Must be a folder
                            ImportFeed(feed, null);
                        }
                    }
                }
                else
                {
                    // Not a valid OPML/XML file
                    throw new ImportExportException(string.Format(Strings.ImportExport_ImportFileNotValid, file), file);
                }
            }
            catch (Exception ex)
            {
                throw new ImportExportException(string.Format(Strings.ImportExport_ImportExportException, file),
                    file, ex);
            }
        }

        private static void ImportFeed(XElement feed, Channel parentChannel)
        {
            parentChannel = parentChannel == null ? ChannelDataSource.Instance.AddNewFolder(feed.Attribute("title").Value) : parentChannel;
            foreach (XElement child in feed.Elements("outline").ToList())
            {
                if (!child.HasElements)
                {
                    ChannelDataSource.Instance.AddChannel(child.Attribute("xmlUrl").Value, parentChannel);
                }
                else
                {
                    parentChannel = ChannelDataSource.Instance.AddNewFolder(child.Attribute("title").Value);
                    ImportFeed(child, parentChannel);
                }
            }
        }
        #endregion

        #region Export
        /// <summary>
        /// Export feed data to a OPML/XML file.
        /// </summary>
        /// <param name="file">
        /// Where to save the OPML/XMl file.
        /// </param>
        public static void Export(string file)
        {
            XElement feeds = null;
            try
            {
                feeds = new XElement("opml");
                feeds.Add(new XAttribute("version", "1.1"));
                feeds.Add(new XElement("head", new XElement("title", "RSS Feeds")));
                feeds.Add(new XElement("body"));

                foreach (Channel channel in ChannelDataSource.Instance.Channels)
                {
                    ExportChildFeeds(channel, feeds.Element("body"));
                }

                feeds.Save(file);
            }
            catch (Exception ex)
            {
                throw new ImportExportException(string.Format(Strings.ImportExport_ImportExportException, file),
                    file, ex);
            }
        }

        /// <summary>
        /// Add Child feeds to OPML.
        /// </summary>
        /// <param name="channel">Channel to add and check for children.</param>
        /// <param name="feed">Feed to append child items to.</param>
        private static void ExportChildFeeds(Channel channel, XElement feed)
        {
            XElement childFeed = new XElement("outline");
            childFeed.Add(new XAttribute("text", channel.Title));
            childFeed.Add(new XAttribute("title", channel.Title));

            if (channel.ChannelType == ChannelType.Feed)
            {
                childFeed.Add(new XAttribute("type", "rss"));
                childFeed.Add(new XAttribute("xmlUrl", channel.Url));
                childFeed.Add(new XAttribute("htmlUrl", channel.Link));
                feed.Add(childFeed);
            }
            else
            {
                feed.Add(childFeed);
                foreach (Channel child in channel.Children)
                {
                    ExportChildFeeds(child, childFeed);
                }
            }
        }
        #endregion
    }
}
